package ro.flashbite.helpers
{
	import ro.flashbite.errors.DontInstanciateError;

	/**
	 * Static helpers for working with numbers
	 * 
	 * v 1.0
	 * 
	 * @author Adrian Barbu
	 */	
	public final class MathHelpers
	{
		public function MathHelpers() { throw new DontInstanciateError(); }
		
		/**
		 * Generates a random number between min and max; Using default params, this mimics Math.random();
		 * 
		 * @param min : (Number) inferior value for randomness
		 * @param max : (Number) superior value for randomness
		 * @return : (Number) random number between min and max
		 */		
		public static function random(min:Number = 0, max:Number = 1):Number
		{
			return (min + Math.random()*(max - min));
		}
		
		/**
		 * Generates a random int between min and max;
		 * 
		 * @param min : (Number) inferior value for randomness
		 * @param max : (Number) superior value for randomness
		 * @return : (int) random rounded value to int between min and max
		 */		
		public static function randomInt(min:Number, max:Number):int
		{
			//return random(min, max); //copy-paste code for performance issues
			return (min + Math.random()*(max - min));
		}
		
		/**
		 * Clamps a numbers between 2 bounds.
		 * 
		 * @param value : (Number) value to clamp
		 * @param min : (Number) min value of clamp
		 * @param max : (Number) max value of clamp
		 * @return : (Number) min if value < min, max if value > max, value if it's inbetween
		 */
		public static function clamp(value:Number, min:Number, max:Number):Number
		{
			if (value < min) return min;
			if (value > max) return max;
			return value;
		}
		
		/**
		 * Tells if a number is in a range
		 *  
		 * @param value : (Number) value to check
		 * @param rangeDown : (Number) bottom value of the range
		 * @param rangeUp : (Number) upper value of the range
		 * @return : (Boolean) true if is in range, false otherwise
		 */		
		public static function isBetween(value:Number, rangeDown:Number, rangeUp:Number):Boolean
		{
			return ((value >= rangeDown) && (value <= rangeUp));	
		}
		
		/**
		 * Determines if a number is even
		 * 
		 * @param value : (int) number to check
		 * @return : (Boolean) true if the number is even, false otherwise
		 */
		public static function isEven(value:int):Boolean 
		{
			return (value & 1) == 0;
		}
		
		/**
		 * Determines if a number is odd
		 * 
		 * @param value : (int) number to check
		 * @return : (Boolean) true if the number is odd, false otherwise
		 * 
		 */
		public static function isOdd(value:int):Boolean 
		{
			//return !isEven(nmb); //copy-paste code for performance issues
			return (value & 1) == 1;
		}
		
		/**
		 * Rounds a number to a specific number of decimals
		 * 
		 * @param value : (Number) the value to be rounded
		 * @param numDecimals : (uint) number of decimals after comma
		 * @return : (Number) the number rounded to specific number of decimals
		 */
		public static function roundToDecimals(value:Number, numDecimals:uint):Number 
		{
			var p:Number = Math.pow(10, numDecimals);
			
			return Math.round(value * p) / p;
		}
		
		/**
		 * Adds a leading zero for numbers less than ten
		 * 
		 * @param value : (int) value to use
		 * @return : (String) the number as String if bigger than 9, otherwise adds a zero
		 */
		public static function addLeadingZero(value:int):String
		{
			return (value >= 0 && value < 10) ? "0" + value : value.toString();
		}
		
		/**
		 * Converts bytes to Kilobytes fast way
		 * 
		 * @param bytes : (Number) the value in bytes
		 * @return : (Number) the number of bytes converted in Kilobytes
		 */
		public static function bytesToKb(bytes:Number):Number 
		{
			return bytes >> 10;
		}
		
		/**
		 * Converts bytes to Megabytes, fast way
		 * 
		 * @param bytes : (Number) the value in bytes
		 * @return : (Number) the number of bytes converted in Megabytes
		 */
		public static function bytesToMb(bytes:Number):Number 
		{
			return bytes >> 20;
		}
	}
}